/* file nd_app.c
 * nd engine server application interface
 *
 * neil duan
 * 2008-6
 */
#include "nd_common/nd_os.h"
#include "nd_crypt/nd_crypt.h"
#include "nd_net/nd_netlib.h"
#include "nd_app.h"


#ifdef WIN32

#ifdef ND_DEBUG
#pragma comment(lib,"nd_srvcore_dbg.lib")
#pragma comment(lib,"nd_net_dbg.lib")
#pragma comment(lib,"nd_crypt_dbg.lib")
#pragma comment(lib,"nd_common_dbg.lib")
#else 
#pragma comment(lib,"nd_srvcore.lib")
#pragma comment(lib,"nd_net.lib")
#pragma comment(lib,"nd_crypt.lib")
#pragma comment(lib,"nd_common.lib")
#endif 

#pragma comment(lib,"Ws2_32.lib")
#include <conio.h>

#else 
	#ifndef DEBUG_WITH_GDB
		#define HANDLE_UNIX_SIGNAL 1        //handle unix signal
	#endif

#endif
#define MAX_CONNECTS  1100
extern void install_start_session() ;

extern NDINT32 create_rsa_key();

extern NDINT32 accept_entry(ND_SESSION_T nethandle, SOCKADDR_IN *addr, nd_handle h_listen) ;

extern void close_entry(ND_SESSION_T nethandle, nd_handle h_listen)  ;

extern NDINT32 pre_close_entry(ND_SESSION_T nethandle, nd_handle h_listen) ;


extern NDINT32 start_timer_srv(ndtime_t interval) ;
void install_message_entries(nd_handle listen_handle) ;

static nd_handle listen_handle ;

static size_t session_size = 0 ;

ndchar_t *__config_file ;

NDINT32 io_mod = ND_LISTEN_UDT_STREAM;// ND_LISTEN_OS_EXT;// ND_LISTEN_COMMON;//ND_LISTEN_UDT_DATAGRAM;// ; //

ndchar_t *srv_getconfig() 
{
	return __config_file ;
}

nd_handle get_listen_handle()
{
	return listen_handle ;
}

void set_session_size(size_t size)
{
	session_size = size ;
}

NDINT32 init_module()
{
	if(-1 == nd_common_init() ) {
		nd_logfatal("init common error!\n") ;
		return -1 ;
    }

	if(-1 == nd_net_init() ) {
		nd_logfatal("init net error!\n") ;
		return -1 ;
    }

	if(-1 == nd_srvcore_init() ) {
		nd_logfatal("init srvcore error!\n") ;
		return -1 ;
    }
    
	return 0 ;
}

void destroy_module() 
{
	nd_srvcore_destroy() ;
	nd_net_destroy() ;
	nd_common_release() ;
}

NDINT32 init_server_app(struct srv_config *run_config)
{
	NDINT32 ssize = 0;
	create_rsa_key() ;
	
	
	//open net server 
	listen_handle = nd_object_create(run_config->listen_name) ;
	if(!listen_handle) {
		nd_logfatal("create object!\n") ;
		return -1 ;
	}
	
#ifdef SINGLE_THREAD_MOD
	nd_listensrv_set_single_thread(listen_handle) ;
#else

	//set listen attribute
	if(session_size < sizeof(player_header_t))
		session_size = sizeof(player_header_t) ;
	
	ssize = session_size + nd_getclient_hdr_size(((struct listen_contex*)listen_handle)->io_mod) ;
#endif
	if(-1==nd_listensrv_session_info(listen_handle, run_config->max_connect, ssize) ) {
		nd_logfatal("create client map allocator!\n") ;
		return -1 ;
	}

	ND_SET_ONCONNECT_ENTRY(listen_handle,accept_entry,pre_close_entry,close_entry) ;
	//nd_listensrv_set_entry(listen_handle,accept_entry,pre_close_entry,close_entry) ;
	
	nd_srv_msgtable_create(listen_handle, MSG_CLASS_NUM, MAXID_BASE) ;
	
	install_start_session(listen_handle) ;
	
	ND_INSTALL_HANDLER(listen_handle,srv_echo_handler,MAXID_SYS,SYM_ECHO,EPL_CONNECT) ;

	ND_INSTALL_HANDLER(listen_handle,srv_broadcast_handler,MAXID_SYS,SYM_BROADCAST,EPL_CONNECT) ;

	//set crypt function
	nd_net_set_crypt((nd_netcrypt)nd_TEAencrypt, (nd_netcrypt)nd_TEAdecrypt, sizeof(tea_v)) ;
	
	if(-1==nd_listensrv_open(run_config->port,   listen_handle)  ) {
		nd_logfatal("open port!\n") ;
		return -1 ;
	}

#ifndef SINGLE_THREAD_MOD
	if(-1==start_timer_srv(5000) ) {
		nd_logfatal("start time server!\n") ;
		return -1 ;
	}
#endif
/**/		
	return 0;
}

//start server
NDINT32 start_server(NDINT32 argc, NDINT8 *argv[])
{
	NDINT32 i ;
	NDINT8 *config_file = NULL;
	struct srv_config readcfg = {0} ;

#ifndef WIN32
	//prctl(PR_SET_DUMPABLE, 1);
#ifdef  HANDLE_UNIX_SIGNAL
	block_signal() ;
#endif 
#endif	
	nd_arg(argc, argv);
	
	if(-1==init_module() ) 
		return -1 ;
	
	//get config file 	
	for (i=1; i<argc-1; i++){
		if(0 == ndstrcmp(argv[i],"-f")) {
			config_file = argv[i+1] ;
			break ;
		}
	}

	if(!config_file) {
		ndprintf("usage: -f config-file\n press ANY key to continue\n") ;
		getch() ;
		exit(1) ;
		//return -1 ;
	}
	__config_file = config_file ;
	if(-1==read_config(config_file, &readcfg) ) {
		ndprintf("press ANY key to continue\n") ;
		getch() ;
		exit(1) ;
	}
	//end get config file

	if(-1==init_server_app(&readcfg) ) {
		return -1 ;
	}
	
	return 0;
}

NDINT32 end_server(NDINT32 force)
{
	/*nd_thsrvid_t timerid = get_timer_thid() ;
	if(timerid) {
		nd_thsrv_destroy(timerid,0) ;
	}*/
	nd_host_eixt() ;
	if(listen_handle) {
		nd_srv_msgtable_destroy(listen_handle) ;
	
		nd_object_destroy(listen_handle,0) ;
		listen_handle = 0 ;
	}
	nd_thsrv_release_all() ;
	destroy_rsa_key() ;
	destroy_module()  ;
	
ndprintf("end server\n") ;
	return 0;
}


NDINT32 wait_services()
{
#ifdef WIN32
	NDINT32 ch;
	while( !nd_host_check_exit() ){
		if(kbhit()) {
			ch = getch() ;
			if(ND_ESC==ch){
				printf_dbg("you are hit ESC, program eixt\n") ;
				break ;
			}
		}
		else {
			nd_sleep(1000) ;
		}
	}
#else
	
#ifdef     HANDLE_UNIX_SIGNAL
	
	while(!nd_host_check_exit() ){
		if(-1==wait_signal_entry() ) {
			printf_dbg("exit from wait signal!\n") ;
			break ;
		}
	}
	unblock_signal() ;
#else 
	NDINT32 ch;
#ifndef DEBUG_WITH_GDB
	installed_sig_handle();
#endif
	while( !nd_host_check_exit() ){
		if(kbhit()) {
			ch = getch() ;
			if(ND_ESC==ch){
				printf_dbg("you are hit ESC, program eixt\n") ;
				break ;
			}
		}
		else {
			nd_sleep(1000) ;
		}
	}
#endif
#endif
	return 0;
}
